package jp.shts.ohos.storiesprogressview;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.util.ArrayList;
import java.util.List;

public class StoriesProgressView extends DirectionalLayout {
    private HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0, "StoriesProgressView");

    private final LayoutConfig PROGRESS_BAR_LAYOUT_PARAM = new LayoutConfig(0, LayoutConfig.MATCH_PARENT, DirectionalLayout.HORIZONTAL, 1);
    private final LayoutConfig SPACE_LAYOUT_PARAM = new LayoutConfig(5, LayoutConfig.MATCH_CONTENT);

    private final List<PausableProgressBar> progressBars = new ArrayList<>();

    private int storiesCount = -1;
    /**
     * pointer of running animation
     */
    private int current = -1;
    private StoriesListener storiesListener;

    private boolean isComplete;

    private boolean isSkipStart;
    private boolean isReverseStart;

    public interface StoriesListener {
        void onNext();

        void onPrev();

        void onComplete();
    }

    public StoriesProgressView(Context context) {
        this(context, null);
    }

    public StoriesProgressView(Context context, AttrSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public StoriesProgressView(Context context, AttrSet attrs, String styleName) {
        super(context, attrs, styleName);
        init(context, attrs);
    }

    private void init(Context context, AttrSet attrSet) {
        setOrientation(DirectionalLayout.HORIZONTAL);
        // 取不到参数报错
        try {
            storiesCount = attrSet.getAttr("progressCount").get().getIntegerValue();
        } catch (Exception e) {
            HiLog.info(TAG, "getAttr progressCount", e.getMessage());
        }
        bindViews();
    }

    private void bindViews() {
        progressBars.clear();
        removeAllComponents();

        for (int i = 0; i < storiesCount; i++) {
            final PausableProgressBar progressBar = createProgressBar();
            progressBars.add(progressBar);
            addComponent(progressBar);
            if ((i + 1) < storiesCount) {
                addComponent(createSpace());
            }
        }
    }

    private PausableProgressBar createProgressBar() {
        PausableProgressBar progressBar = new PausableProgressBar(getContext());
        progressBar.setLayoutConfig(PROGRESS_BAR_LAYOUT_PARAM);
        return progressBar;
    }

    private Component createSpace() {
        Component component = new Component(getContext());
        component.setLayoutConfig(SPACE_LAYOUT_PARAM);
        return component;
    }

    /**
     * Set story count and create views
     *
     * @param storiesCount story count
     */
    public void setStoriesCount(int storiesCount) {
        this.storiesCount = storiesCount;
        bindViews();
    }

    /**
     * Set storiesListener
     *
     * @param storiesListener StoriesListener
     */
    public void setStoriesListener(StoriesListener storiesListener) {
        this.storiesListener = storiesListener;
    }

    /**
     * Skip current story
     */
    public void skip() {
        if (isSkipStart || isReverseStart) {
            return;
        }
        if (isComplete) {
            return;
        }
        if (current < 0) {
            return;
        }
        PausableProgressBar progressBar = progressBars.get(current);
        isSkipStart = true;
        progressBar.setMax();
    }

    /**
     * Reverse current story
     */
    public void reverse() {
        if (isSkipStart || isReverseStart) {
            return;
        }
        if (isComplete) {
            return;
        }
        if (current < 0) {
            return;
        }
        PausableProgressBar progressBar = progressBars.get(current);
        isReverseStart = true;
        progressBar.setMin();
    }

    /**
     * Set a story's duration
     *
     * @param duration millisecond
     */
    public void setStoryDuration(long duration) {
        for (int i = 0; i < progressBars.size(); i++) {
            progressBars.get(i).setDuration(duration);
            progressBars.get(i).setCallback(callback(i));
        }
    }

    /**
     * Set stories count and each story duration
     *
     * @param durations milli
     */
    public void setStoriesCountWithDurations(long[] durations) {
        storiesCount = durations.length;
        bindViews();
        for (int i = 0; i < progressBars.size(); i++) {
            progressBars.get(i).setDuration(durations[i]);
            progressBars.get(i).setCallback(callback(i));
        }
    }

    private PausableProgressBar.Callback callback(final int index) {
        return new PausableProgressBar.Callback() {
            @Override
            public void onStartProgress() {
                current = index;
            }

            @Override
            public void onFinishProgress() {
                if (isReverseStart) {
                    if (storiesListener != null) {
                        storiesListener.onPrev();
                    }
                    if ((current - 1) >= 0) {
                        PausableProgressBar progressBar = progressBars.get(current - 1);
                        progressBar.setMinWithoutCallback();
                        progressBars.get(--current).startProgress();
                    } else {
                        progressBars.get(current).startProgress();
                    }
                    isReverseStart = false;
                    return;
                }
                int next = current + 1;
                if ((progressBars.size() - 1) >= next) {
                    if (storiesListener != null) {
                        storiesListener.onNext();
                    }
                    progressBars.get(next).startProgress();
                } else {
                    isComplete = true;
                    if (storiesListener != null) {
                        storiesListener.onComplete();
                    }
                }
                isSkipStart = false;
            }
        };
    }

    /**
     * Start progress animation
     */
    public void startStories() {
        reset();
        progressBars.get(0).startProgress();
    }

    /**
     * Start progress animation from specific progress
     *
     * @param from 开始的位置
     */
    public void startStories(int from) {
        for (int i = 0; i < from; i++) {
            progressBars.get(i).setMaxWithoutCallback();
        }
        reset();
        progressBars.get(from).startProgress();
    }

    /**
     * Need to call when Ability or Fraction destroy
     */
    public void destroy() {
        for (PausableProgressBar progressBar : progressBars) {
            progressBar.clear();
        }
    }

    /**
     * Need to call when startStories
     */
    public void reset() {
        for (PausableProgressBar progressBar : progressBars) {
            progressBar.reset();
        }
    }

    /**
     * Pause story
     */
    public void pause() {
        if (current < 0) {
            return;
        }
        progressBars.get(current).pauseProgress();
    }

    /**
     * Resume story
     */
    public void resume() {
        if (current < 0) {
            return;
        }
        progressBars.get(current).resumeProgress();
    }
}
